package com.cdu.guoxinan.www.smartcom.service;

import com.cdu.guoxinan.www.smartcom.domian.dto.AddRequestDTO;
import com.cdu.guoxinan.www.smartcom.domian.dto.RequestDTO;
import com.cdu.guoxinan.www.smartcom.domian.dto.ResidentQueryDTO;
import com.cdu.guoxinan.www.smartcom.domian.pojo.Resident;
import com.cdu.guoxinan.www.smartcom.domian.vo.DashboardStatVo;
import com.cdu.guoxinan.www.smartcom.domian.vo.FeeVO;
import com.cdu.guoxinan.www.smartcom.domian.vo.RepairApplyVO;
import com.cdu.guoxinan.www.smartcom.service.impl.EmpStatisticsServiceImpl;
import com.cdu.guoxinan.www.smartcom.service.impl.FeeServiceImpl;
import com.cdu.guoxinan.www.smartcom.service.impl.ResidentServiceImpl;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Flux;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class AIService {
    @Value("${ai.model}")
    private String model;
    @Value("${ai.url}")
    private String url;
    @Value("${ai.stream}")
    private Boolean stream;

    @Resource
    private RestTemplate restTemplate;
    @Resource
    private EmpStatisticsServiceImpl empStatisticsService;
    @Resource
    private ResidentServiceImpl residentService;
    @Resource
    private RepairApplyService repairApplyService;

    @Resource
    private FeeServiceImpl feeService;

    /**
     * 流式传输，优先拦截固定问题返回固定答案
     *
     * @param prompt 用户输入的问题
     * @param use_id
     * @return 返回回答的Flux流，如果没有匹配则调用AI接口
     */
    public Flux<String> streamQuery(String prompt, Long use_id) {
        // 先尝试拦截固定问题
        Flux<String> intercepted = extractResponse(prompt, use_id);
        if (intercepted != null) {
            return intercepted;
        }

        // 如果没有匹配固定问题，则调用AI接口
        Map<String, Object> map = new HashMap<>();
        map.put("model", model);
        map.put("prompt", prompt);
        map.put("stream", stream);
        return WebClient.create()
                .post()
                .uri(url)
                .contentType(MediaType.APPLICATION_JSON)
                .bodyValue(map)
                .retrieve()
                .bodyToFlux(String.class)
                .map(this::extractResponseChunk)
                .filter(text -> !text.isEmpty());
    }

    /**
     * 解析AI接口返回的JSON，提取响应文本
     * @param json AI接口返回的JSON字符串
     * @return 响应文本
     */
    private String extractResponseChunk(String json) {
        try {
            JsonNode node = new ObjectMapper().readTree(json);
            return node.path("response").asText();
        } catch (Exception e) {
            return "";
        }
    }

    /**
     * 非流式调用AI接口，整体返回响应内容
     * @param prompt 用户输入
     * @return AI接口返回的回答
     */
    public String queryModel(String prompt) {
        Map<String, Object> request = new HashMap<>();
        request.put("model", model);
        request.put("prompt", prompt);
        request.put("stream", false);

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);

        ResponseEntity<Map> response = restTemplate.exchange(
                url,
                HttpMethod.POST,
                new HttpEntity<>(request, headers),
                Map.class
        );
        if (response.getStatusCode() == HttpStatus.OK && response.getBody() != null) {
            return (String) response.getBody().get("response");
        }
        throw new RuntimeException("Ollama API 调用失败: " + response.getStatusCode());
    }

    /**
     * 拦截用户输入中的固定问题，返回对应的固定答案
     * @param prompt 用户输入的问题
     * @return 如果匹配固定问题，返回对应答案的Flux流；否则返回null
     */
    private String extractNameFromPrompt(String prompt) {
        // 只捕获中文姓名，确保姓名后面没有“的”或“信息”
        java.util.regex.Pattern pattern = java.util.regex.Pattern.compile(".*查询[\\s\u3000]*([\\u4e00-\\u9fa5]+)(?=\\s*的).*");
        java.util.regex.Matcher matcher = pattern.matcher(prompt);
        if (matcher.find()) {
            return matcher.group(1); // 返回捕获的中文姓名
        }
        return null;
    }

    private Flux<String> extractResponse(String prompt, Long use_id) {
        if (prompt == null) {
            return null;
        }
        String lower = prompt.toLowerCase();
        // 现有拦截代码
        if (lower.contains("小区") && lower.contains("居民") && lower.contains("数量")) {
            try {
                DashboardStatVo stats = empStatisticsService.getDashboardStats();
                return Flux.just("当前小区共有居民" + stats.getResidentCount() + "人");
            } catch (Exception e) {
                return Flux.just("抱歉，无法获取居民数据。");
            }
        }
        if (lower.contains("你是谁") || lower.contains("你叫什么名字")) {
            return Flux.just("我是智能小区系统AI助手，专注于为社区管理提供智能化服务");
        }
        if (lower.contains("你能做什么") || lower.contains("你能帮我们做什么")) {
            return Flux.just("我可以帮助您查询小区数据、分析统计信息、提供建议等");
        }
        if (lower.contains("介绍一下你自己") || lower.contains("介绍下你的功能")) {
            return Flux.just("我是智慧社区AI助手，基于大数据与AI技术，服务于社区居民与管理人员");
        }
        if (lower.contains("物业费") && (lower.contains("发票") || lower.contains("收据"))) {
            return Flux.just("物业费缴费成功后，可在订单详情中下载电子发票或前往物业窗口领取纸质发票。");
        }
        if (lower.contains("车位") && (lower.contains("申请") || lower.contains("如何办理"))) {
            return Flux.just("您可以前往物业服务中心提交车位申请，物业会根据空余情况为您分配。");
        }
        if (lower.contains("投诉") && (lower.contains("怎么") || lower.contains("流程"))) {
            return Flux.just("您可以通过小区APP提交投诉，物业会在24小时内处理并反馈结果。");
        }
        if (lower.contains("建议") && (lower.contains("提交") || lower.contains("如何"))) {
            return Flux.just("您可以在【意见反馈】模块提交您的建议，我们将认真考虑改进。");
        }
        if (lower.contains("订单") && (lower.contains("状态") || lower.contains("查订单"))) {
            return Flux.just("您可以在【我的订单】中查看订单状态，支持按订单号或商品名称搜索。");
        }
        if (lower.contains("订单") && (lower.contains("取消") || lower.contains("能取消吗"))) {
            return Flux.just("订单在未支付前可以取消，进入订单详情点击【取消订单】即可。");
        }
        if (lower.contains("订单") && (lower.contains("退款") || lower.contains("退货"))) {
            return Flux.just("订单支付成功后可申请退款，请联系客服或前往售后中心处理。");
        }
        if (lower.contains("个人信息") && (lower.contains("修改") || lower.contains("更新"))) {
            return Flux.just("您可以在【个人中心】中修改基本信息，部分信息需通过物业审核。");
        }
        if (lower.contains("住户") && (lower.contains("登记") || lower.contains("如何登记"))) {
            return Flux.just("新增住户请携带身份证前往物业服务中心办理登记手续。");
        }
        if (lower.contains("房产证") && (lower.contains("办理") || lower.contains("如何"))) {
            return Flux.just("房产证办理请联系开发商或前往不动产登记中心办理。");
        }
        if (lower.contains("房产") && (lower.contains("过户") || lower.contains("变更"))) {
            return Flux.just("房产过户需携带相关材料前往不动产登记中心办理，物业协助提供必要证明。");
        }
        if (lower.contains("商品") && (lower.contains("优惠") || lower.contains("打折"))) {
            return Flux.just("您可以在【促销活动】页面查看当前正在进行的商品优惠活动。");
        }
        if (lower.contains("快递") && (lower.contains("领取") || lower.contains("取件"))) {
            return Flux.just("您好，快递请到小区物业服务中心领取，地址在1号楼一楼大厅。");
        }
        if (lower.contains("商品") && (lower.contains("缺货") || lower.contains("没货了"))) {
            return Flux.just("该商品暂时缺货，建议您关注补货通知或选择其他替代商品。");
        }
        if (lower.contains("快递柜") && (lower.contains("位置") || lower.contains("在哪"))) {
            return Flux.just("小区设有两个快递柜，分别位于1号楼和3号楼旁。");
        }
        if (lower.contains("健身房") && (lower.contains("开放时间") || lower.contains("几点开门"))) {
            return Flux.just("小区健身房开放时间为早上6点至晚上10点。");
        }
        if (lower.contains("儿童乐园") && (lower.contains("开放时间") || lower.contains("几点关门"))) {
            return Flux.just("儿童乐园开放时间为早上8点至晚上9点，节假日延长至10点。");
        }
        // 1. 查询社区规则
        if (lower.contains("社区") && lower.contains("规则")) {
            return Flux.just("社区规则可以在app的'社区指南'部分找到，也可以在官方网站上查看。关键规则包括：禁止乱扔垃圾、保持公共区域安静、遵守停车规定等。");
        }

        // 2. 预约社区设施
        if (lower.contains("预约") && lower.contains("社区") && lower.contains("设施")) {
            return Flux.just("您可以通过app的'预约'部分预约社区设施。选择您需要的设施（如会议室或健身房），选择日期和时间，按照提示完成预约。");
        }

        // 3. 查询即将举行的社区活动
        if (lower.contains("社区") && lower.contains("活动") && (lower.contains("即将") || lower.contains("最近") || lower.contains("有哪些"))) {
            return Flux.just("有关即将举行的社区活动的最新信息，请查看app的'活动'部分或访问社区公告板。");
        }

        // 4. 报告丢失物品
        if (lower.contains("报告") && lower.contains("丢失") && lower.contains("物品")) {
            return Flux.just("要报告丢失物品，请前往app的'失物招领'部分提交报告，提供物品的详细信息。您也可以直接联系物业管理办公室。");
        }

        // 5. 查询入住/退出的程序
        if ((lower.contains("入住") || lower.contains("退出")) && lower.contains("程序")) {
            return Flux.just("入住或退出请至少提前7天通知物业管理。您需要完成必要的文书工作并安排接通或断开公用事业。详细程序可以在app的'搬迁指南'中找到。");
        }

        // 6. 获取访客通行证
        if (lower.contains("访客") && lower.contains("通行证")) {
            return Flux.just("要获取访客通行证，您可以通过app的'访客管理'部分申请，或者访问物业管理办公室为您的客人颁发通行证。");
        }

        // 7. 查询废物处理指南
        if (lower.contains("废物") && lower.contains("处理")) {
            return Flux.just("废物处理指南如下：垃圾需分类投放，厨余垃圾、可回收物和有害垃圾分别放入指定垃圾桶。有关详细信息，请参考app中的'废物管理'部分。");
        }

        // 8. 接入社区Wi-Fi
        if (lower.contains("社区") && lower.contains("wi-fi")) {
            return Flux.just("要接入社区Wi-Fi，请连接到名为'CommunityWiFi'的网络并输入密码'Welcome2023'。如需帮助，请联系物业管理。");
        }

        // 9. 查询宠物政策
        if (lower.contains("宠物") && lower.contains("政策")) {
            return Flux.just("宠物政策包括：每户限养一只宠物，需登记并佩戴牵引绳，禁止在公共区域随意遛狗。有关更多详情，请查看app中的'宠物指南'或联系物业管理。");
        }

        // 10. 加入社区通讯
        if (lower.contains("加入") && lower.contains("社区") && lower.contains("通讯")) {
            return Flux.just("要加入社区通讯，请前往app的'通讯'部分并订阅。您也可以在物业管理办公室提供您的电子邮件。");
        }

        // 11. 查询安全措施
        if (lower.contains("安全") && lower.contains("措施")) {
            return Flux.just("社区实施了多项安全措施，包括24小时监控、准入控制系统和定期巡逻。有关更多详情，请参考app中的'安全信息'部分。");
        }

        // 12. 申请备用钥匙卡
        if (lower.contains("备用") && lower.contains("钥匙") && lower.contains("卡")) {
            return Flux.just("要申请备用钥匙卡，请携带您的身份证件前往物业管理办公室，并支付50元的费用。");
        }

        // 13. 查询社区中心开放时间
        if (lower.contains("社区中心") && (lower.contains("开放时间") || lower.contains("开门"))) {
            return Flux.just("社区中心开放时间为每天上午8点至晚上8点。对于特殊活动，开放时间可能有所不同，请查看活动时间表。");
        }

        // 14. 参与社区清洁日
        if (lower.contains("参与") && lower.contains("社区") && lower.contains("清洁")) {
            return Flux.just("要参与社区清洁日，请查看app中的'志愿者机会'部分，了解即将举行的活动并报名参加。您也可以联系社区委员会获取更多信息。");
        }

        // 15. 组织社区活动的流程
        if (lower.contains("组织") && lower.contains("社区") && lower.contains("活动")) {
            return Flux.just("要组织社区活动，请通过app的'活动提案'部分向社区委员会提交提案。包括活动日期、时间、地点和目的等详细信息。委员会将审查并批准或提供反馈。");
        }

        // 16. 访问数字邮箱
        if (lower.contains("数字") && lower.contains("邮箱")) {
            return Flux.just("您的数字邮箱可以通过app的'邮件'部分访问。您需要使用您的凭证登录以查看和管理您的邮件。");
        }

        // 17. 查询噪音规定
        if (lower.contains("噪音") && lower.contains("规定")) {
            return Flux.just("噪音规定禁止在晚上10点至次日早上6点制造大声噪音。请尊重您的邻居并在此期间保持噪音水平低。");
        }

        // 18. 获取单位技术问题的帮助
        if (lower.contains("技术") && lower.contains("问题") && lower.contains("单位")) {
            return Flux.just("对于单位内的技术问题，请通过app的'维护请求'部分提交维护请求。详细描述问题，我们的团队将尽快为您提供帮助。");
        }

        // 19. 查询紧急联系号码
        if (lower.contains("紧急") && lower.contains("联系") && lower.contains("号码")) {
            return Flux.just("在紧急情况下，请联系：消防119，急救120，物业管理123-4567-8901。对于非紧急情况，您可以拨打物业管理电话。");
        }

        // 20. 对社区服务提供反馈
        if (lower.contains("提供") && lower.contains("反馈") && lower.contains("社区") && lower.contains("服务")) {
            return Flux.just("要对社区服务提供反馈，请前往app的'反馈'部分并提交您的评论或建议。您也可以将电子邮件发送到feedback@community.com。");
        }

        // 21. 查询最近的医院
        if (lower.contains("最近") && lower.contains("医院")) {
            return Flux.just("社区附近的最近医院是阳光医院，位于阳光路123号。您可以通过app中的地图功能获取方向。");
        }

        // 22. 支付公用事业账单
        if (lower.contains("支付") && lower.contains("公用事业") && lower.contains("账单")) {
            return Flux.just("公用事业账单可以通过app的'账单支付'部分支付。选择您的公用事业提供商，输入金额，并使用可用方式完成支付。");
        }

        // 23. 查询回收选项
        if (lower.contains("回收") && lower.contains("选项")) {
            return Flux.just("社区提供纸张、塑料和金属的回收箱。请将您的可回收物分类并放入指定的回收箱中。有关更多信息，请查看app中的'废物管理'指南。");
        }

        // 24. 加入社区健身房
        if (lower.contains("加入") && lower.contains("社区") && lower.contains("健身房")) {
            return Flux.just("要加入社区健身房，请通过app的'健身中心'部分注册。支付会员费后，您将收到访问凭证。");
        }

        // 25. 查询停车规定
        if (lower.contains("停车") && lower.contains("规定")) {
            return Flux.just("停车规定包括：需持有有效停车许可，访客停车区禁止过夜停车。有关详细信息，请参考app中的'停车规则'。");
        }
        if (lower.contains("查询") && lower.contains("个人信息")) {
            String name = extractNameFromPrompt(prompt);
            if (name != null && !name.isEmpty()) {
                ResidentQueryDTO dto = new ResidentQueryDTO();
                dto.setName(name);
                PageInfo<Resident> pageInfo = residentService.queryPage(dto);
                if (pageInfo.getList() != null && !pageInfo.getList().isEmpty()) {
                    StringBuilder sb = new StringBuilder("以下是").append(name).append("的居民信息：\n");
                    for (Resident r : pageInfo.getList()) {
                        sb.append("姓名: ").append(r.getName()).append("\n")
                                .append("性别: ").append(r.getGender() == 1 ? "男" : "女").append("\n")
                                .append("联系电话: ").append(r.getPhoneNumber()).append("\n");
                    }
                    return Flux.just(sb.toString());
                } else {
                    return Flux.just("未找到名为" + name + "的居民信息。");
                }
            } else {
                return Flux.just("请输入要查询的居民姓名，例如：“请查询张三的个人信息”");
            }
        }
        if (lower.contains("查询") && lower.contains("物业费")) {
            String name = extractNameFromPrompt(prompt);
            if (name != null && !name.isEmpty()) {
                List<FeeVO> fees =empStatisticsService.getFeeByName(name); // 获取费用列表

                if (fees == null || fees.isEmpty()) {
                    return Flux.just("未找到名为 " + name + " 的物业费记录。");
                }

                StringBuilder sb = new StringBuilder(name).append("的物业费记录如下：\n");

                for (int i = 0; i < fees.size(); i++) {
                    FeeVO fee = fees.get(i);
                    String feeType = fee.getFeeType() == 1 ? "物业费" : "车位费";
                    String amount = String.valueOf(fee.getAmount());
                    String status = fee.getStatus() == 1 ? "已缴" : "未缴";

                    sb.append("</br>【记录 ").append(i + 1).append("】")
                            .append("  </br>费用类型: ").append(feeType).append("\n")
                            .append("  金额:     ").append(amount).append(" 元\n")
                            .append("  状态:     ").append(status).append("\n");
                }

                return Flux.just(sb.toString());
            } else {
                return Flux.just("请输入要查询的居民姓名，例如：“请查询张三的物业费”");
            }
        }



        // 拦截所有包含“维修”的请求，并自动创建维修申请
        if (lower.contains("维修") && prompt.length() > 10) {
            // 构造维修申请对象
            AddRequestDTO dto = new AddRequestDTO();
            dto.setDescription(prompt);             // 使用用户输入作为描述
            dto.setResidentId(empStatisticsService.getResidentId(use_id));
            dto.setPriority(2);              // 默认优先级为“中”
            dto.setStatus(1);                // 状态为“待处理”

            try {
                int result = repairApplyService.addRepairApply(dto);
                if (result > 0) {
                    return Flux.just("已为您创建维修申请，描述为：" + prompt);
                } else {
                    return Flux.just("创建维修申请失败，请稍后再试。");
                }
            } catch (Exception e) {
                return Flux.just("系统错误：创建维修申请失败。");
            }
        }


        // 未匹配任何固定问题，返回null，继续调用AI接口
        return null;
    }
}
